<?php

namespace CMS\Update\Libs;

/**
 * Trida pro dump databaze.
 *
 * @author David Dusek
 */

class DumpDatabase {    
    public $output;
    private $tables = array();        
    private $dropTableIfExists = true;
    private $numericTypes = array(
                                    "tinyint", 
                                    "smallint",
                                    "mediumint",
                                    "int",
                                    "integer",
                                    "bigint",
                                    "double",
                                    "float",
                                    "real",
                                    "decimal",
                                  );
    
    /**
     * Aktualni pripojeni k databazi.
     * @var \Doctrine\DBAL\Connection 
     */
    private $connection;
    
    /**
     * Konstruktor bere jeden parametr a to aktualni pripojeni k databazi.
     * @param \Doctrine\DBAL\Connection $connection 
     */
    public function __construct($connection) {
        $this->connection = $connection;
    }
    
    /**
     * Nastaveni jestli se ma pred vytvorenim tabulka odebrat.
     * @param bool $value
     */
    public function setDropTableIfExists($value) {
        $this->dropTableIfExists = $value;
    }
        
    /**
     * Vygeneruje dumb databaze do atributu output. 
     */
    function dump() {
        $this->output = "-- FIT-CMS database dump\n"
                      . "-- Date and time: " . date("Y-m-d H:i:s" . "\n\n")
                      . "SET FOREIGN_KEY_CHECKS=0;";
        
        $this->listTables();
        foreach ($this->tables as $table) {
            $this->dumpTable($table);
        }
        
        $this->output .= "\nSET FOREIGN_KEY_CHECKS=1;\n";
    }

    /**
     * Vytvoreni pole s nazvy vsech tabulek databaze a jejich ulozeni v atributu
     * tables. 
     */
    private function listTables() {        
        $this->tables = array();
        $rows = $this->connection->fetchAll("SHOW TABLES");
        foreach ($rows as $row) {         
            $keys = array_keys($row);
            array_push($this->tables, $row[$keys[0]]);
        }
    }
    
    /**
     * Dump jedne tabulky urcene parametrem tablename.
     * @param string $tablename Nazev tabulky.
     */
    function dumpTable($tablename) {       
        $this->getTableStructure($tablename);
        $this->getTableValues($tablename);
    }
    
     /**
     * Vygenerovani create skriptu struktury pro jednu tabulku. 
     * @param string $tablename Nazev tabulky.
     */
    function getTableStructure($tablename) {
        $this->output .= "\n\n-- --------------------------------------------\n";
        $this->output .= "-- Dumping structure for table: $tablename\n";
        $this->output .= "-- --------------------------------------------\n\n";
        if ($this->dropTableIfExists) {
            $this->output .= "DROP TABLE IF EXISTS `$tablename`;\n";
        }
       
        $res = $this->connection->fetchAssoc("SHOW CREATE TABLE `$tablename`");
        $this->output .= $res["Create Table"] . ";\n";
    }

    /**
     * Vytvoreni insertu pro vsechny zaznamy v tabulce zadane parametrem 
     * tablename.
     * @param string $tablename Nazev tabulky.
     */
    function getTableValues($tablename) {
        $rows = $this->connection->fetchAll("SELECT * FROM `$tablename`");
        
        if (!empty($rows)) {
            $this->output .= "\n\n-- Dumping data for table: $tablename\n\n";        
            
            $cols = $this->connection->fetchAll("SHOW COLUMNS FROM `$tablename`");
                
            $colsNames = "";
            $colsIsNumeric = array();
            foreach ($cols as $col) {
                $colsNames .= "`" . $col["Field"] . "` ,";
                $colType = substr($col["Type"], 0, strpos($col["Type"], '('));
                $colType = strtolower($colType);
                $colsIsNumeric[$col["Field"]] = in_array($colType, $this->numericTypes);
            }
            $colsNames = substr($colsNames, 0, -2);
            
            $this->output .= "INSERT INTO `$tablename` ($colsNames) VALUES\n";
            
            $values = "";
            foreach ($rows as $row) {
                $line = "(";
                foreach ($row as $colName => $colVal) {
                    if (!$colsIsNumeric[$colName]) {                        
                        $colVal = str_replace("\\", "\\\\", $colVal);
                        $colVal = "'$colVal'";
                    }
                    $line .= "$colVal, ";
                }
                $values .= substr($line, 0, -2) . "),\n";
            }
            
            $this->output .= substr($values, 0, -2) . ";\n";
        }
    }    
}
